package proxy

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"go-gateworker/internal/balancer"
	"go-gateworker/internal/config"
	"go-gateworker/internal/models"
)

// RouteMap 路由映射
type RouteMap struct {
	rules     map[string]*config.RouteRule
	balancers map[string]*balancer.LoadBalancer
	mu        sync.RWMutex
}

// Proxy 结构体只保留 routeMap、metrics、mu
// 移除 ProxyTask 结构体、taskChan 字段、workerLoop 方法
// ServeHTTP 直接调用 handleRequest
type Proxy struct {
	routeMap      *RouteMap
	metrics       *ProxyMetrics
	mu            sync.RWMutex
	cfg           *config.Config
	configWatcher *config.Watcher
	// 限流相关字段
	rateLimiter    *RateLimiter
	// 请求超时
	requestTimeout time.Duration
}

// ProxyMetrics 代理指标
type ProxyMetrics struct {
	TotalRequests     int64
	FailedRequests    int64
	AverageLatency    float64
	TotalLatency      float64
	ProcessedRequests int64
}

// New 创建新的代理，支持协程池
func New(cfg *config.Config, configPath string) *Proxy {
	p := &Proxy{
		routeMap: &RouteMap{
			rules:     make(map[string]*config.RouteRule),
			balancers: make(map[string]*balancer.LoadBalancer),
		},
		metrics:        &ProxyMetrics{},
		cfg:            cfg,
		requestTimeout: time.Duration(cfg.ServerSettings.RequestTimeout) * time.Second,
	}
	
	// 初始化路由规则和负载均衡器
	p.updateFromConfig(cfg)
	
	// 设置限流器
	p.rateLimiter = NewRateLimiter(cfg.Gateway.RateLimits)
	
	// 如果提供了配置路径，设置配置监视器
	if configPath != "" {
		watcher, err := config.NewWatcher(configPath)
		if err != nil {
			log.Printf("[ERROR] 初始化配置监视器失败: %v", err)
		} else {
			p.configWatcher = watcher
			// 注册配置变更回调
			p.configWatcher.RegisterCallback(p.onConfigChange)
			
			// 启动配置监视
			if err := p.configWatcher.Start(); err != nil {
				log.Printf("[ERROR] 启动配置监视失败: %v", err)
			}
		}
	}
	
	return p
}

// 从配置更新代理
func (p *Proxy) updateFromConfig(cfg *config.Config) {
	p.mu.Lock()
	defer p.mu.Unlock()
	
	// 保存新配置
	p.cfg = cfg
	
	// 更新请求超时
	p.requestTimeout = time.Duration(cfg.ServerSettings.RequestTimeout) * time.Second
	
	// 清空旧的路由规则和负载均衡器
	oldBalancers := p.routeMap.balancers
	p.routeMap.rules = make(map[string]*config.RouteRule)
	p.routeMap.balancers = make(map[string]*balancer.LoadBalancer)
	
	// 初始化路由规则和负载均衡器（原有逻辑）
	for _, rule := range cfg.RouteRules {
		p.routeMap.rules[rule.PathPrefix] = &rule
		var servers []*models.Server
		for _, serverCfg := range rule.Servers {
			server, err := models.NewServer(serverCfg)
			if err != nil {
				log.Printf("[ERROR] 为 %s 创建服务器失败: %v", serverCfg.URL, err)
				continue
			}
			servers = append(servers, server)
		}
		
		// 检查是否有现有的负载均衡器可以更新
		if lb, exists := oldBalancers[rule.PathPrefix]; exists {
			lb.UpdateServers(servers)
			p.routeMap.balancers[rule.PathPrefix] = lb
		} else {
			p.routeMap.balancers[rule.PathPrefix] = balancer.New(servers, balancer.Config{
				Strategy:    balancer.StrategyLeastConn,
				Threshold:   int64(cfg.Gateway.ProcessSettings.MaxRequestsPerWorker),
				HealthCheck: cfg.HealthCheck,
			})
		}
	}
	
	// 关闭不再使用的负载均衡器
	for path, lb := range oldBalancers {
		if _, exists := p.routeMap.balancers[path]; !exists {
			lb.Stop()
		}
	}
	
	log.Printf("[INFO] 代理配置已更新，共加载 %d 个路由规则", len(p.routeMap.rules))
}

// 配置变更回调函数
func (p *Proxy) onConfigChange(newCfg *config.Config) {
	log.Printf("[INFO] 检测到配置变更，正在更新代理...")
	p.updateFromConfig(newCfg)
	
	// 更新限流配置
	p.rateLimiter.UpdateLimits(newCfg.Gateway.RateLimits)
}

// ServeHTTP 直接处理请求
func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	p.handleRequest(w, r)
}

// handleRequest 处理实际请求（原 ServeHTTP 逻辑）
func (p *Proxy) handleRequest(w http.ResponseWriter, r *http.Request) {
	start := time.Now()
	
	// 生成请求ID并添加到响应头
	requestID := fmt.Sprintf("%d%d", time.Now().UnixNano(), time.Now().Unix()%1000)
	w.Header().Set("X-Request-ID", requestID)
	
	// 创建请求上下文的日志记录
	log.Printf("[INFO] [%s] 开始处理请求: %s %s", requestID, r.Method, r.URL.Path)
	
	// 限流检查
	if p.rateLimiter != nil && !p.rateLimiter.Allow(r.URL.Path) {
		p.incrementFailedRequests()
		w.WriteHeader(http.StatusTooManyRequests)
		w.Write([]byte("Rate limit exceeded"))
		log.Printf("[WARN] [%s] 请求被限流: %s %s", requestID, r.Method, r.URL.Path)
		return
	}
	
	// 路由匹配
	matchedPrefix, rule, balancer := p.getRouteRule(r.URL.Path)
	if rule == nil || balancer == nil {
		p.incrementFailedRequests()
		http.Error(w, "Invalid path", http.StatusBadRequest)
		log.Printf("[WARN] [%s] 无效的路径: %s", requestID, r.URL.Path)
		return
	}
	
	// 健康检查
	if balancer.GetHealthyServerCount() == 0 {
		p.incrementFailedRequests()
		http.Error(w, "Service not found", http.StatusNotFound)
		log.Printf("[ERROR] [%s] 所有服务器都不可用，路径: %s", requestID, r.URL.Path)
		return
	}
	
	// 设置请求上下文超时
	ctx, cancel := context.WithTimeout(r.Context(), p.requestTimeout)
	defer cancel()
	r = r.WithContext(ctx)
	
	// 请求转发
	err := p.tryForwardRequest(w, r, matchedPrefix, balancer)
	duration := time.Since(start).Seconds()
	
	if err != nil {
		p.incrementFailedRequests()
		if ctx.Err() == context.DeadlineExceeded {
			log.Printf("[ERROR] [%s] 请求超时: %s %s, 耗时: %.2fs", 
				requestID, r.Method, r.URL.Path, duration)
		} else {
			log.Printf("[ERROR] [%s] 请求转发失败: %s %s, 错误: %v, 耗时: %.2fs", 
				requestID, r.Method, r.URL.Path, err, duration)
		}
		// 不写任何响应，全部交由 ReverseProxy.ErrorHandler 兜底
		return
	}
	
	p.updateMetrics(duration)
	log.Printf("[INFO] [%s] 请求处理完成: %s %s, 耗时: %.2fs", 
		requestID, r.Method, r.URL.Path, duration)
}

// tryForwardRequest 尝试转发请求
func (p *Proxy) tryForwardRequest(w http.ResponseWriter, r *http.Request, pathPrefix string, lb *balancer.LoadBalancer) error {
	// 获取服务器 - 熔断器会拦截此调用
	server := lb.GetServer()
	if server == nil {
		return fmt.Errorf("没有可用的服务器")
	}
	
	// 检查熔断状态
	if server.CircuitBreaker != nil && !server.CircuitBreaker.BeforeRequest() {
		return fmt.Errorf("服务器熔断中")
	}
	
	// 增加服务器负载计数
	if !server.IncrementLoad() {
		return fmt.Errorf("服务器负载过高")
	}
	defer server.DecrementLoad()
	
	// 获取请求ID用于日志关联
	requestID := r.Header.Get("X-Request-ID")
	if requestID == "" {
		requestID = w.Header().Get("X-Request-ID")
	}

	// 打印原始路径和匹配到的前缀
	log.Printf("[DEBUG] [%s] 原始请求路径: %s, 匹配到的前缀: %s", requestID, r.URL.Path, pathPrefix)

	// 克隆请求，避免复用原始对象
	outreq := r.Clone(r.Context())

	// 只处理 path
	newPath := strings.TrimPrefix(r.URL.Path, pathPrefix)
	if !strings.HasPrefix(newPath, "/") {
		newPath = "/" + newPath
	}
	
	log.Printf("[DEBUG] [%s] 去除前缀后的新路径: %s", requestID, newPath)
	outreq.URL.Path = newPath
	outreq.RequestURI = ""

	// 添加请求ID到下游请求
	outreq.Header.Set("X-Request-ID", requestID)
	
	log.Printf("[INFO] [%s] 转发请求到: %s%s?%s", 
		requestID, server.URL.String(), outreq.URL.Path, outreq.URL.RawQuery)

	// 创建响应记录器，用于捕获响应状态
	rw := NewResponseWriter(w)
	
	// 发送请求
	startTime := time.Now()
	server.ReverseProxy.ServeHTTP(rw, outreq)
	duration := time.Since(startTime)
	
	// 获取响应状态，更新熔断器
	statusCode := rw.Status()
	success := statusCode >= 200 && statusCode < 500
	
	if server.CircuitBreaker != nil {
		server.CircuitBreaker.AfterRequest(success)
	}
	
	// 记录响应结果
	if !success {
		log.Printf("[WARN] [%s] 后端返回错误状态: %d, 耗时: %v", 
			requestID, statusCode, duration)
		return fmt.Errorf("后端返回错误状态: %d", statusCode)
	}
	
	log.Printf("[DEBUG] [%s] 后端响应成功: %d, 耗时: %v", 
		requestID, statusCode, duration)
	return nil
}

// ResponseWriter 响应写入器包装
type ResponseWriter struct {
	http.ResponseWriter
	status int
	size   int
}

// NewResponseWriter 创建新的响应写入器
func NewResponseWriter(w http.ResponseWriter) *ResponseWriter {
	return &ResponseWriter{
		ResponseWriter: w,
		status:         http.StatusOK,
	}
}

// WriteHeader 写入状态码
func (r *ResponseWriter) WriteHeader(status int) {
	r.status = status
	r.ResponseWriter.WriteHeader(status)
}

// Write 写入响应体
func (r *ResponseWriter) Write(b []byte) (int, error) {
	size, err := r.ResponseWriter.Write(b)
	r.size += size
	return size, err
}

// Status 获取状态码
func (r *ResponseWriter) Status() int {
	return r.status
}

// Size 获取响应大小
func (r *ResponseWriter) Size() int {
	return r.size
}

// copyHeaders 复制 HTTP 头
func copyHeaders(dst, src http.Header) {
	for k, vv := range src {
		for _, v := range vv {
			dst.Add(k, v)
		}
	}
}

// logRequestInfo 记录请求信息
func logRequestInfo(method, originalPath, query, newPath, serverURL string, body []byte) {
	log.Printf("请求方法: %s", method)
	log.Printf("原始路径: %s", originalPath)
	log.Printf("目标服务器: %s", serverURL)

	if method == http.MethodPost && len(body) > 0 {
		maxBodyLog := 1024
		bodyStr := string(body)
		if len(bodyStr) > maxBodyLog {
			bodyStr = bodyStr[:maxBodyLog] + "..."
		}
	}
}

// getRouteRule 根据路径获取路由规则和对应的负载均衡器
func (p *Proxy) getRouteRule(path string) (string, *config.RouteRule, *balancer.LoadBalancer) {
	p.routeMap.mu.RLock()
	defer p.routeMap.mu.RUnlock()

	var matchedPrefix string
	var matchedRule *config.RouteRule
	for prefix, rule := range p.routeMap.rules {
		if strings.HasPrefix(path, prefix) {
			if len(prefix) > len(matchedPrefix) {
				matchedPrefix = prefix
				matchedRule = rule
			}
		}
	}
	if matchedRule == nil {
		return "", nil, nil
	}
	log.Printf("getRouteRule: 路径 %s 匹配到前缀 %s", path, matchedPrefix)
	return matchedPrefix, matchedRule, p.routeMap.balancers[matchedPrefix]
}

// UpdateRouteRules 更新路由规则
func (p *Proxy) UpdateRouteRules(rules []config.RouteRule) {
	p.routeMap.mu.Lock()
	defer p.routeMap.mu.Unlock()

	p.routeMap.rules = make(map[string]*config.RouteRule)
	for _, rule := range rules {
		p.routeMap.rules[rule.PathPrefix] = &rule
	}
}

// updateMetrics 更新代理指标
func (p *Proxy) updateMetrics(duration float64) {
	p.mu.Lock()
	defer p.mu.Unlock()

	atomic.AddInt64(&p.metrics.TotalRequests, 1)
	atomic.AddInt64(&p.metrics.ProcessedRequests, 1)

	// 更新平均延迟
	p.metrics.TotalLatency += duration
	p.metrics.AverageLatency = p.metrics.TotalLatency / float64(p.metrics.ProcessedRequests)

	log.Printf("请求完成，耗时 %.2fs，平均延迟 %.2fs", duration, p.metrics.AverageLatency)
}

// incrementFailedRequests 增加失败请求计数
func (p *Proxy) incrementFailedRequests() {
	atomic.AddInt64(&p.metrics.FailedRequests, 1)
}

// GetMetrics 获取代理指标
func (p *Proxy) GetMetrics() ProxyMetrics {
	p.mu.RLock()
	defer p.mu.RUnlock()
	return *p.metrics
}
